package com.wtgroup.demo.mianshi.线程.d04_线程池;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * @author dafei
 * @version 0.1
 * @date 2021/3/11 10:20
 */
public class D2_ForkJoin {


    public static void main(String[] args) {
        /*
        * 1+2+...+1_0000_0000
        * 单线程;
        * Fork/Join
        *   1. 实现task子类, 实现具体计算. (RecursiveTask, RecursiveAction)
        *   2. 提交给 ForkJoinPool 执行.
        * */

        int END = 1_0000_0000;

        long t0 = System.currentTimeMillis();
        int s = 0;
        for (int i = 1; i <= END; i++) {
            s += i;
        }
        System.out.println(s);
        System.out.println(System.currentTimeMillis() - t0);


        long t1 = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        CountTask task = new CountTask(1, END);
        ForkJoinTask<Integer> res = forkJoinPool.submit(task);
        try {
            System.out.println(res.get());
            System.out.println(System.currentTimeMillis() - t1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static class CountTask extends RecursiveTask<Integer> {
        public static final int THRESHOLD = 100_0000;
        private final int start;
        private final int end;

        public CountTask(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            /*
            * 不足阈值, 直接计算, 输出结果; 否则, 继续拆分任务.
            * */

            int sum = 0;
            if (end - start <= THRESHOLD) {
                for (int i = start; i <= end; i++) {
                    sum += i;
                }

                return sum;
            }

            int mid = (this.end + this.start) / 2;
            CountTask leftTask = new CountTask(start, mid);
            CountTask rightTask = new CountTask(mid + 1, end);

            leftTask.fork();
            rightTask.fork();
            Integer left = leftTask.join();
            Integer right = rightTask.join();
            return left + right;
        }
    }




}
